package org.jeecg.modules.drive.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.modules.device.entity.DevDeviceInfo;
import org.jeecg.modules.drive.entity.DevDriveModel;
import org.jeecg.modules.drive.mapper.DevDriveModelMapper;
import org.jeecg.modules.drive.service.DriveCommonInterfaceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Service
public class DriveCommonInterfaceServiceImpl implements DriveCommonInterfaceService {

    @Autowired
    private DevDriveModelMapper driveModelMapper;
    @Autowired
    private RestTemplate restTemplate;

    //接口模式
    @Override
    public List<Map<String, Object>> readDeviceDataByInterface(DevDeviceInfo deviceInfo){
        if(null == deviceInfo){
            throw new JeecgBootException("设备不存在");
        }
        /**
         * 水表	1
         * 压力表	2
         * 阀门开关	3
         * 监控抓拍	4
         * 视频监控	5
         * 水位	6
         * 雨量	7
         * 温度	8
         * 湿度	9
         */
        String deviceType = deviceInfo.getDeviceType();//设备类型
        DevDriveModel driveModel=  driveModelMapper.selectById(deviceInfo.getDriveId());
        if(null == driveModel){
            throw new JeecgBootException("设备所在设备驱动为空");
        }

        /***
         * 1. 是否模型为空
         * 2. token是否存在
         * 3. token是否到期
         * 4. 动态获取token
         * 5. 返回token并保存
         */

        driveModel.getDriveLoginHostPort();
        driveModel.getDriveLoginPost();
        driveModel.getDriveLoginApi();
        driveModel.getDriveApiUsername();
        driveModel.getDriveApiPassword();
        driveModel.getDriveResultType();
        driveModel.getDriveResultStatus();
        driveModel.getDriveResultMessage();
        driveModel.getDriveResultData();
        driveModel.getDriveResultDataKey();

        String requestRul = driveModel.getDriveLoginHostPort()+driveModel.getDriveLoginApi();
        JSONObject param = new JSONObject();
        param.put(driveModel.getDriveApiUserkey(),driveModel.getDriveApiUsername());
        param.put(driveModel.getDriveApiPwdkey(),driveModel.getDriveApiPassword());


        /***
         * 设备编码 需要对应 读取数据n 值
         */
        String devKey= driveModel.getReadDataType1().equals(deviceType)? driveModel.getDriveReadData1() :
                driveModel.getReadDataType2().equals(deviceType)?driveModel.getDriveReadData2():
                        driveModel.getReadDataType3().equals(deviceType)?driveModel.getDriveReadData3():
                                driveModel.getReadDataType4().equals(deviceType)?driveModel.getDriveReadData4():
                                        driveModel.getReadDataType5().equals(deviceType)?driveModel.getDriveReadData5():
                                                driveModel.getReadDataType6().equals(deviceType)?driveModel.getDriveReadData6():
                                                        driveModel.getReadDataType7().equals(deviceType)?driveModel.getDriveReadData7(): "";
        if(StringUtils.isEmpty(devKey)){
            throw new JeecgBootException("设备类型配置不能为空");
        }

        return null;
    }

    //接口模式- 返回监控设备的播放地址
    @Override
    public String getMonitorDevicePlayByInterface(DevDeviceInfo deviceInfo){
        if(null == deviceInfo){
            throw new JeecgBootException("设备不存在");
        }
        DevDriveModel driveModel = driveModelMapper.selectById(deviceInfo.getDriveId());
        if(null == driveModel){
            throw new JeecgBootException("设备所在设备驱动为空");
        }

        /***
         * 1. 是否模型为空
         * 2. token是否存在
         * 3. token是否到期
         * 4. 动态获取token
         * 5. 返回token并保存
         */
        String requestRul = driveModel.getDriveLoginHostPort()+driveModel.getDriveLoginApi();
        JSONObject param = new JSONObject();
        param.put(driveModel.getDriveApiUserkey(),driveModel.getDriveApiUsername());
        param.put(driveModel.getDriveApiPwdkey(),driveModel.getDriveApiPassword());

        if(StringUtils.isEmpty(driveModel.getDriveLoginHostPort())
                || StringUtils.isEmpty(driveModel.getDriveLoginApi())
                || StringUtils.isEmpty(driveModel.getDriveApiUsername())
                || StringUtils.isEmpty(driveModel.getDriveApiUserkey())
                || StringUtils.isEmpty(driveModel.getDriveApiPwdkey())
                || StringUtils.isEmpty(driveModel.getDriveApiPassword())
                || StringUtils.isEmpty(driveModel.getDriveResultStatus())
                || StringUtils.isEmpty(driveModel.getDriveResultDataKey())
        ){
            throw new JeecgBootException("设备驱动模型不完整");
        }

        /**2. token是否存在 */
        if(StringUtils.isNotEmpty(driveModel.getAccessToken()) && StringUtils.isNotEmpty(driveModel.getExpireTime())){
            String expireTime = driveModel.getExpireTime(); // long 毫秒数
            long ctime = new Date().getTime();
            long expireDateTime = Long.parseLong(expireTime);
            /**3. token是否到期 */
            if(expireDateTime > ctime){
                // 到期时间大于当前时间  =》 可以直接使用
                return driveModel.getPlayAddress();
            }else{
                /**4. 动态获取token*/
                JSONObject resEntityBody = this.restTemplatePost(requestRul, param,driveModel.getDriveResultStatus());
                return this.accessTokenNext(resEntityBody, driveModel.getId()
                        , driveModel.getDriveResultData(), driveModel.getDriveResultDataKey());
            }
        }else{
            /**4. 动态获取token*/
            JSONObject resEntityBody = this.restTemplatePost(requestRul, param,driveModel.getDriveResultStatus());
            return this.accessTokenNext(resEntityBody, driveModel.getId()
                    , driveModel.getDriveResultData(), driveModel.getDriveResultDataKey());
        }
    }

    public String accessTokenNext(JSONObject resEntityBody, String modelId
            , String resultDataKey, String accessTokenKey ){
        if(null != resEntityBody ){
            if(StringUtils.isEmpty(resultDataKey)){
                // 没有下一级对象，直接读取token
                String token = resEntityBody.getString(accessTokenKey);
                String accessExpireTime = resEntityBody.getString("expireTime");
                /*** 5. 返回token并保存 */
                String playAddress = this.saveDeviceModel(modelId, token, accessExpireTime);
                return playAddress;
            }else {
                // 数据在下一级
                Object resDataObj = resEntityBody.get(resultDataKey);
                if (resDataObj instanceof LinkedHashMap) {
                    LinkedHashMap resData = (LinkedHashMap) resDataObj;
                    String token = resData.get(accessTokenKey)+"";
                    String accessExpireTime = resData.get("expireTime")+"";

                    /*** 5. 返回token并保存 */
                    String playAddress = this.saveDeviceModel(modelId,token,accessExpireTime);
                    return playAddress;
                }else if (resDataObj instanceof JSONObject) {
                    JSONObject resData = (JSONObject) resDataObj;
                    String token = resData.getString(accessTokenKey);
                    String accessExpireTime = resData.getString("expireTime");

                    /*** 5. 返回token并保存 */
                    String playAddress = this.saveDeviceModel(modelId,token,accessExpireTime);
                    return playAddress;
                }else if(resDataObj instanceof JSONArray){
                    JSONArray resDataLs = (JSONArray)resDataObj;
                    JSONObject resData = (JSONObject)resDataLs.get(0);
                    String token = resData.getString(accessTokenKey);
                    String accessExpireTime = resData.getString("expireTime");
                    /*** 5. 返回token并保存 */
                    String playAddress = this.saveDeviceModel(modelId,token,accessExpireTime);
                    return playAddress;
                }
            }
        }
        return null;
    }

    /***
     * 保存驱动模型token
     * @param modelId
     * @param token
     * @param accessExpireTime
     */
    public String saveDeviceModel(String modelId,String token,String accessExpireTime) {
        DevDriveModel model = new DevDriveModel();
        // 播放地址拼接 https://open.ys7.com/console/jssdk/pc.html?accessToken=?&url=ezopen://open.ys7.com/?/1.hd.live&themeId=standard
        String urlStr="https://open.ys7.com/console/jssdk/pc.html?accessToken=" + token
                + "&url=ezopen://open.ys7.com/??/1.live&themeId=standard";
        model.setId(modelId);
        model.setAccessToken(token);
        model.setPlayAddress(urlStr);
        model.setExpireTime(StringUtils.isNotEmpty(accessExpireTime) ? accessExpireTime : new Date().getTime()+"");
        model.setAccessTime(new Date().getTime()+"");
        driveModelMapper.updateById(model);
        return urlStr;
    }


    // restTemplate 请求
    public JSONObject restTemplatePost(String requestRul,JSONObject param, String statusCode){

        StringBuilder sb = new StringBuilder();
        for (String key : param.keySet()) {
            sb.append("&");
            sb.append(key +"="+param.getString(key));
        }

        String substring = sb.substring(1);
        requestRul =  requestRul+"?"+substring;

        System.out.println(requestRul);
        param.put("Content-Type","application/x-www-form-urlencoded");
        ResponseEntity<JSONObject> resEntity =  restTemplate.postForEntity(requestRul, param, JSONObject.class);
        JSONObject resEntityBody = resEntity.getBody();
        System.out.println(resEntityBody.toJSONString());
        if( null != resEntityBody.getString(statusCode)  &&  "200".equals(resEntityBody.getString(statusCode))){
            return resEntityBody;
        }
        return null;
    }


}
